# Tactical Battle Scripts by Victorious (24 Mar 2015)

# about these scripts

Documentation and information about the latest version of these scripts can be found here and downloaded here.

These scripts were written to extend Tactical Battle's functionality. The scripts primary focus for now is on allowing you to do more with effects. To use these scripts, extract the .zip archive to the data for tb folder. In your map pack's Map Pack Settings.txt file, add the following:

load_scripts victorious

or if you are already using other scripts, append victorious to the end of that line.

# a warning about infinite recursion

These scripts are very powerful and if not used properly will cause tactical battle to go into an infinite loop and crash. For example, you have effects_on_apply Y set on effect x, and effects_on_apply x on effect y. Being affected by x causes y to be applied and vice versa, creating an infinite cycle. Though this is a trivial mistake that most people would intuitively avoid making, it may happen in more complex cases such as using replace_effects, effects_on_apply and effects_on_remove together.

# Preliminary notes

- When I refer to a unit in a script, it'll work identically for structures unless stated otherwise.
- scripted effects/skills/items refer to the effect/item/skill that a script flag is being used from
- The new script flag format is being used here, which looks like this: flag arguments. Unlike the previous format, there is no equals sign between the flag and the argument, and spaces are allowed in arguments. For example: replace_effects clouds|clouds, thunderstorm|thunderstorm, none|cool air
- It is important for the script to accurately determine the target of the scripted item/skill/effect. If it detects the tile or empty_tile flag, then the target is determined to be a tile. The target is determined to be a unit if the following flags are set: enemy, friendly, no_self_cast, self and unit. In situations where contradicting flags are set such as tile and enemy, tile flags take presidence in the determination. If none of these flags are set, then the script will inform you that no decision can be made.

# Effect Flags

## Optional Duration Modifiers

Most of these scripts will require you to specify effects that will be applied to a target. It is usually done by a comma seperated list of effects such as: poison, plague. In addition to specifying the effect that you want applied, you may also append optional modifiers to the effect to change its duration using the following format: EffectName[modifier]. The modifier, if specified, must be enclosed in square brackets []. The following modifiers are supported:

- integer: overrides the effect's duration with that integer
- +integer and -integer: adds or subtracts the specified integer to the effect's original duration
- *NonNegativeRealNumber: multiplies the effect's base duration with a nonnegative real number. The result is rounded to the nearest integer.

This allows having different durations for the same effect depending on where the effect is used, without creating duplicates of the same effect with different durations.

Examples: If the magma tile effect has a duration of 5,

- specifying magma in a list of effects to be applied applies it normally with no duration modifications. In this case, it lasts for 5 rounds.
- magma[+8] in an effect list applies magma with 5+8 = 13 rounds.
- magma[-3] applies magma with 8-3 = 5 rounds.
- magma[*2.2] applies magma with 2.2*5 = 11 rounds.
- magma[*2.5] applies magma with 2.5*5 = 12.5 rounds, which is rounded up to 13 rounds.
- magma[*3.25] applies magma with 3.25*5 = 16.25, which gets rounded down to 16 rounds.
- magma[1000] applies magma with 1000 rounds.

## effects_on_entry, remove_effects_on_entry

Argument: string, where string is a single effect or a list of unit effects, each separated by a comma followed by a space. Optional duration modifiers can be used with effects_on_entry

Useable on: tile effects

Applies or removes a list of unit effects to all units entering the tile affected by the scripted tile effect. Not_affects_flying on tile effects is respected for these flags. Because there is currently no actual before or after movement event for scripters to use, this only works if the target uses an item or skill to move onto the tile. It will not work if the target was moved onto the tile by a script. This is also the reason why there aren't corresponding flags for leaving the tile.

Examples:

- If you have a spider unit, its web could cause units to be caught in it when moving into the tile using effects_on_entry entanglement
- On a more powerful spider that has a stronger web, you could use effects_on_entry entanglement[*2] to cause it to last twice the number of rounds

## effects_on_apply, effects_on_fizzle and effects_on_remove

Argument: string, where string is a single effect or a list of effects, each separated by a comma followed by a space. Optional duration modifiers can be used with all 3 flags.

Useable on: both tile and unit effects for effects_on_apply and effects_on_remove. Only unit effects for effects_on_fizzle.

Applies a list of additional effects upon the application, fizzling or removal of the scripted effect. This can be particularly useful if you want multiple effects to happen when a point reaches zero (because the game only allows you to specify a single one). Effects_on_fizzle can only be used on unit effects at this time because the effect fizzling event currently does not fire on tile effects. Effect application is performed in the following way:

- Tile effects will be applied regardless of whether the scripted effect is a tile or unit effect
- Unit effects will be applied to all occupants of the tile if the script effect is a tile effect. Unit effects are only applied to the target for unit scripted effects.

Examples:

- if you wanted a greater elemental shield to fizzle into a lesser elemental shield instead of vanishingly entirely on its effect duration: effects_on_fizzle lesser elemental shield. Note that greater elemental shield must be a unit effect for this to work, but there is no such restriction on lesser elemental shield.
- effects_on_apply exhaustion, vulnerability
- effects_on_fizzle vulnerability
- effects_on_remove exhaustion, vulnerability

## map_preload_effects

Argument: string, where string contains tile-effect associations separated by a semicolon, followed by a space. A tile-effect association has the following format: x, y = effect_1, effect_2, effect_n. X and Y are 1-based coordinates of tiles - for example, 1,1 is the top left corner of the map. Optional duration modifiers may be used in the effects list.

Useable on: maps

Applies a list of effects on tiles and units for some coordinates upon map load. This can be useful if you need effects with extra scripted functionality that can't be achieved with terrain.

- If the effect specified is a tile effect, it will be applied to the tile.
- If the effect is a unit effect, it will be applied to all occupants on the tile.

The coordinates these scripts use correspond to those displayed with the "y-coordinates decrease as you move up" setting turned off in TB options. These effects will not be reapplied if a saved game is reloaded. This script works when the map is opened in the map editor, which is useful for ensuring that effects are being applied on the right tiles.

Examples:

- To preload the tile effect poison cloud and the unit effect poison on all units in 2,10: map_preload_effects 2, 10 = poison cloud, poison
- To apply the tile effect lava on 2,10 and 2,11: map_preload_effects 2, 10 = lava; 2, 11 = lava
- Duration modifiers can be used to easily ensure that applied effects last for the game's duration. For example, map_preload_effects 2, 10 = lava[1000]; 2, 11 = lava[1000]

## remove_effects_on_apply, remove_effects_on_fizzle, remove_effects_on_remove

Argument: string, where string is a single effect or a list of effects, each separated by a comma followed by a space.

Useable on: both tile and unit effects for remove_effects_on_apply and remove_effects_on_remove. Only unit effects for remove_effects_on_fizzle.

Removes a list of effects upon the application, fizzling or removal of the scripted effect. Remove_effects_on_fizzle only supports unit effects at this time because the effect fizzling event currently does not fire on tile effects. Effect removal is performed in the following way:

- Tile effects will be removed regardless of whether the scripted effect is a tile or unit effect
- Unit effects will be removed from all occupants of the tile if the script effect is a tile effect. Unit effects are only removed from the target for unit scripted effects.

Example:

- An example use scenario is making some effects mutually exclusive; instead of specifying remove_effects in the skills that applies effects that aren't compatible, with each other, you only have to specify this once in each effect. To make greater elemental shield mutually exclusive with lesser elemental shield: remove_effects_on_apply lesser elemental shield on the greater elemental shield and vice versa for lesser elemental shield
- on a thunderstorm effect: remove_effects_on_apply forestfire

## replace_effect

Argument: string, where the string consists of effect pairs which must be either both unit or both tile effects. Effect pairs must have the format old effect|new effect. Effect pairs are separated by a comma followed by a space. Optional duration modifiers may be used with the new effect.

Supporting flags: replace_effects_limit (string), where string represents an integer, dice roll or range. This limits the number of successful effect replacements. This flag is optional.

Related flags: replace_occupants_effects

Useable on: tile and unit effects, items, skills

Performs effect replacement, similar to how replace_terrain works. The script applies replacements in the following way:

- If used on an item or skill, the replacements are only attempted if the item/skill usage succeeds. This script supports item/skill with splash range components.
- Pairs of replacements are evaluated from left-to-right.
- If the old and new effect are the same (e.g thunderstorm|thunderstorm), nothing is done, which means that the effect is not reapplied. This is not considered a successful replacement. However, prefixing the new effect with the keyword reapply overrides this behaviour, reapplying the old effect if both effects are the same. For example, (thunderstorm|reapply thunderstorm). Reapplication is considered a successful replacement.
- the tile or unit target in the scripted effect/item/skill is first searched for tile or unit effects that match a replacement pair. If a match is found, the replacement is carried out. This is done until the number of successful replacements reaches the limit (if specified).
- If you want mass effect replacements for effects on multiple occupants of a tile, use the replace_occupants_effects flag, which can be used instead of, or together with replace_effects.

In addition, the none keyword may be usedd in the following way:

- If specified as an old effect (e.g none|level 1), the replacement effect is only applied if the target is not affected by any other effects in the replace_effects line preceeding the current pair. For instance, if the replace_effects line is none|level 1, level 1|level 2 with a replace_effects_limit of 1, level 1 always gets applied (as there is nothing before the first pair) and the rest of the line never gets evaluated, regardless of what other effects are present. In contrast, for replace_effects level 1|level 2, none|level 1 with a replace_effects_limit of 1, level 1 only gets replaced if the target is not affected by both level 1 and 2. If the target is affected by level 1, it is replaced by level 2 and nothing happens when the target has level 2. Though this is potentially confusing, an example is provided below that leverages this useful feature.
- if specified as a new effect (e.g level 6|none), all effects in the replace_effects list preceeding the current pair are removed from the target, if present.
- For obvious reasons, please avoid having a reapply prefix in effects names and having effects named none.

Examples:

- For a warding skill that requires the tile to be first prepared for warding before the warding would succeed, the following can be added in the skill file: replace_effects prepared for warding|powerful ward. Note that it is currently not possible to prevent such a skill from failing if the required effect is not present; the skill still gets executed, but nothing happens.
- to implement a level up skill, a common mistake is to have replace_effects level 1|level 2, level 2|level 3, none|level 1 without the use of a limit. Observe that when the unit is not affected by any level, it will get promoted to level 1 upon the first use of the skill, which works as expected. When it is affected by level 1 and when the skill is used again, it gets promoted to level 2, but then that causes the level 2|level 3 pair to match, promoting it to level 3. Use replace_effects_limit 1 in this situation.

- If you wanted to simulate the creation of weather effects that can do damage to enemies, you would want to restrict the tiles that the weather effects could be applied for. For example, creating a thunderstorm could require the following progression: cool air, cloud formation, thunderstorm. Study the following which is to be placed in the cool air skill:

  replace_effects clouds|clouds, thunderstorm|thunderstorm, none|cool air

  This is actually a very complex use case for this script. The positioning of the none|cool air pair ensures that the cool air effect will only be applied if the tile was not already affected by either clouds or thunderstorm, while not altering existing clouds and thunderstorm effects, if present. You will be able to refresh the duration of the cool air effect if cast on a tile with cool air. To prevent the renewal of the cool air effect, simply insert cool air|cool air somewhere before the none|cool air pair. Alternatively, use cool air|reapply cool air after the none|cool air pair. You can also implement unit effect replacements for occupants of the targeted tile. For example, replace_occupants_effects wet|drenched, none|wet with replace_occupants_effects_limit 1.

- If you can't seem to achieve what you want using replace_effects alone, remember that using it in conjunction with the other effect flags should allow you to implement most effect-related scenarios.

## replace_occupants_effects

Argument: string, where string consists of effect pairs which must be both unit effects. Effect pairs must have the format old effect|new effect. Effect pairs are separated by a comma followed by a space. The new effect in the replacement pair may have optional duration modifiers.

Supporting flags: replace_occupants_effects_limit (string), where string represents an integer, dice roll or range. This limits the number of successful effect replacements per tile occupant, not the number of occupants on the tile that replacements are made for. This flag is optional.

Related flags: replace_effects

Useable on: tile effects, items and skills with tile targets

This is a version of replace_effects which searches all occupants of the target tile for unit effects which can be replaced by other unit effects. Effect replacements are done for all occupants of the tile, subject to the replace_occupants_effects_limit. All other features such as the use of the none keyword are supported, so refer to the replace_effects section for detailed documentation.

## effects_on_failure, self_effects_on_failure, self_tile_effects_on_failure

Argument: string, where string is a single effect or a list of effects, each separated by a comma followed by a space. Optional duration modifiers are supported for all 3 flags.

Useable on: items, skills

Apply/remove a list of effects on item use failure or skill failure.

- Effects_on_failure applies both tile and unit effects to the target. If the target is a unit, unit effects will be applied to only the target. If the target is a tile, unit effects will be applied to all occupants of the tile. Tile effects will always be applied regardless of whether the target is a unit or tile.
- Self_effects_on_failure applies only unit effects to the user of the item or skill.
- Self_tile_effects_on_failure works the same way as effects_on_failure

Examples:

- On a flaming arrow skill which has a unit target: effects_on_failure burning ground. This causes the arrow to set the targeted tile on fire if it misses its target.
- On powerful spells which causes magical backlash to hurt the caster and/or occupants of the caster's tile on spellcasting failure: self_effects_on_failure magical backlash or self_tile_effects_on_failure magical backlash. Magical backlash in this case is a unit effect. To cause magical backlash proportional to the spell's power, you can have a single magical backlash effect which uses duration modifiers depending on the power of the spell to get different effect durations.
- If the item or skill has the self flag set, then all 3 of these flags will work on the same target or area, because the caster itself is the target in this case.

## source_effects_on_apply, source_tile_effects_on_apply, source_effects_on_remove, source_tile_effects_on_remove, remove_source_effects_on_apply, remove_source_tile_effects_on_apply, remove_source_effects_on_remove and remove_source_tile_effects_on_remove (experimental)

Argument: string, where string is a single effect or a list of effects, each separated by a comma followed by a space. Duration modifiers are supported for source_effects_on_apply, source_tile_effects_on_apply, source_effects_on_remove and source_tile_effects_on_remove

Useable on: tile and unit effects

Apply/remove a list of additional effects to the source unit/structure of the scripted effect or the source tile upon application/removal of the scripted effect. Flags with just source as its prefix (e.g source_effects_on_apply, source_effects_on_remove) applies unit effects only to the source, while their source_tile counterparts (source_tile_effects_on_apply, source_tile_effects_on_remove) applies tile effects to the source tile and unit effects to all occupants of the source tile. The other flags work in a similar way. This feature is marked experimental because I cannot garentee being able to determine the source unit, which happens if the effect was applied through scripting. In that case, the most recent unit that used an item or performed a skill is the next best guess used. If the source still cannot be determined, it fails silently. The flags may look very long but should be quite easy to remember; for example, remove_source_tile_effects_on_remove means on the removal of the scripted effect, remove effects from the source tile.

Examples:

- This can be used on trap effects which cause exotically bad things to happen to anyone trying to disarm/remove it
- This can also be used to implement some sort of basic continuous effect such as health or mana drain on the source to sustain an effect. This does not yet account for situations such as the effect that the source is sustaining being removed by someone.

# changelog

- 24 Mar 2015:
  - Fixed a critical bug in replace_effects that caused it to fail for unit targets.
  - Added map_preload_effects, which applies effects to the specified coordinates to the map on map load.
  - When specifying lists of effects to be applied for all flags dealing with effect application (including replace_effects), an optional duration modifier can now be specified in addition to the effect name which changes the applied effect. For instance, map_preload_effects 2, 10 = lava[1000] causes tile 2, 10 to be affected by lava for 1000 rounds, regardless of its actual effect duration. This required significant changes throughout the script, so watch out for bugs.
  - The script now provides a more useful error when it cannot determine if an effect/item/skill applies to a unit or tile
- 21 Mar 2015:
  - Effects_on_entry and remove_effects_on_entry now supports the unit being moved by item usage.
  - Implemented effects_on_failure, self_effects_on_failure and self_tile_effects_on_failure to control what happens to the target and source on item or skill usage failure.
  - When determining the source of an effect, the most recent user of an item is now also used in addition to the most recent unit that used a skill.
  - Fixed some flags that could be specified on items that weren't working as I forgot to hook in the functionality to item events.
  - Fixed a subtle bug that was causing effects to be applied twice for effect applications with a tile as its area of effect. It would apply the effect on the targeted unit (there is a target unit even if you specify a tile in effect/item/skill files) and then do so again when it was applying it to all tile occupants. This could cause unexpected behaviour if the effects to be applied are scripted to respond to effect application.
  - Improved determination of the scripted effect/item/skill's target. From the documentation: it is important for the script to accurately determine the target of the scripted item/skill/effect. If it detects the tile or empty_tile flag, then the target is determined to be a tile. The target is determined to be a unit if the following flags are set: enemy, friendly, no_self_cast, self and unit. In situations where contradicting flags are set such as tile and enemy, tile flags take presidence in the determination. If none of these flags are set, then no decision can be made, which causes many of the scripts to fail.
- 20 Mar 2015:
  - lifted the restrictions on the type of effects that can be used with numerous flags (thanks Craig for making the needed TB changes)
  - Fixed bugs in source_effects_on_remove causing it to remove effects instead of applying them.
  - Added 6 new flags for applying or removing effects from the source unit/tile in response to effect application or removal.
  - Added replace_occupants_effects flag, which does mass effect replacements for all occupants of a tile
  - Added preliminary support for effects_on_entry and remove_effects_on_entry flags on tile effects. This flag respects not_affect_flying flags set on the tile effect.
- 14 Mar 2015:
  - Disabled replace_effects feature where using it on a tile checks all units on it to see if their effects need replacement. This was causing errors.
  - Added reapply keyword on replace_effects to override effects with the same name not being reapplied. This should make replace_effects slightly easier to use while making it more powerful.
- 12 Mar 2015:
  - added source_effects scripts
  - Documentation improvements
- 10 Mar 2015: initial release

# Feedback

Suggestions are welcome. I may be contacted on the Ian Reed's games mailing list.